package io.gitee.zhangbinhub.admin.service

import io.gitee.zhangbinhub.acp.boot.component.FileDownLoadHandle
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.base.BaseService
import io.gitee.zhangbinhub.admin.constant.WorkFlowConstant
import io.gitee.zhangbinhub.admin.po.ProcessDefinitionPo
import io.gitee.zhangbinhub.admin.po.ProcessDefinitionQueryPo
import io.gitee.zhangbinhub.admin.vo.CustomerQueryPageVo
import io.gitee.zhangbinhub.admin.vo.ProcessDefinitionVo
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.dromara.warm.flow.core.FlowEngine
import org.dromara.warm.flow.core.dto.DefJson
import org.dromara.warm.flow.core.entity.Definition
import org.dromara.warm.flow.core.service.DefService
import org.dromara.warm.flow.core.utils.page.Page
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional(transactionManager = "mybatisFlexTransactionManager", readOnly = true)
class WorkFlowDefinitionService(
    private val defService: DefService,
    private val fileDownLoadHandle: FileDownLoadHandle
) : BaseService() {
    private fun definitionToVo(definition: Definition): ProcessDefinitionVo = ProcessDefinitionVo().apply {
        this.id = definition.id.toString()
        this.flowCode = definition.flowCode
        this.flowName = definition.flowName
        this.version = definition.version
        this.category = definition.category
        this.createTime = definition.createTime.time
        this.updateTime = definition.updateTime.time
        this.publishStatus = definition.isPublish
        this.activityStatus = definition.activityStatus
        if (definition.id != null) {
            this.content = defService.exportJson(definition.id)
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun publish(id: Long) {
        if (!defService.publish(id)) {
            throw WebException("流程发布失败！")
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun unPublish(id: Long) {
        if (!defService.unPublish(id)) {
            throw WebException("流程取消发布失败！")
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun active(id: Long) {
        if (!defService.active(id)) {
            throw WebException("流程激活失败！")
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun unActive(id: Long) {
        if (!defService.unActive(id)) {
            throw WebException("流程挂起失败！")
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun create(processDefinitionPo: ProcessDefinitionPo) {
        FlowEngine.newDef().apply {
            this.flowCode = processDefinitionPo.flowCode
            this.flowName = processDefinitionPo.flowName
            this.category = processDefinitionPo.category
            if (!defService.checkAndSave(this)) {
                throw WebException("流程创建失败！")
            }
        }
    }

    @Transactional
    @Throws(WebException::class)
    fun update(processDefinitionPo: ProcessDefinitionPo) {
        defService.getById(processDefinitionPo.id).apply {
            this.flowCode = processDefinitionPo.flowCode
            this.flowName = processDefinitionPo.flowName
            this.category = processDefinitionPo.category
            if (!defService.updateById(this)) {
                throw WebException("流程更新失败！")
            }
        }
    }

    @Transactional
    fun delete(idList: MutableList<Long>) {
        defService.removeDef(idList)
    }

    fun query(processDefinitionQueryPo: ProcessDefinitionQueryPo): CustomerQueryPageVo<ProcessDefinitionVo> =
        defService.orderByCreateTime().desc().page(
            DefJson.copyDef(DefJson().apply {
                this.flowCode = processDefinitionQueryPo.flowCode
                this.flowName = processDefinitionQueryPo.flowName
                this.category = processDefinitionQueryPo.category
            }),
            Page(
                processDefinitionQueryPo.queryParam!!.currPage!!,
                processDefinitionQueryPo.queryParam!!.pageSize!!
            )
        ).let { pageResult ->
            CustomerQueryPageVo(
                totalElements = pageResult.total,
                currPage = pageResult.pageNum,
                pageSize = pageResult.pageSize,
                content = pageResult.list.map { definitionToVo(it) }
            )
        }

    @Transactional
    @Throws(WebException::class)
    fun import(processDefinitionPo: ProcessDefinitionPo) {
        if (!CommonTools.isNullStr(processDefinitionPo.content)) {
            defService.importJson(processDefinitionPo.content!!)
        } else {
            throw WebException("导入内容不能为空！")
        }
    }

    @Throws(WebException::class)
    fun export(request: HttpServletRequest, response: HttpServletResponse, id: Long) {
        defService.getById(id).let { definition ->
            val targetFile = CommonTools.contentWriteToFile(
                WorkFlowConstant.DOWNLOAD_TEMP_PATH + "/${definition.flowName}_${definition.flowCode}_${definition.version}.json",
                defService.exportJson(id)
            )
            val foldPath = targetFile.parentFile.canonicalPath
            fileDownLoadHandle.downLoadFile(
                request, response, targetFile.canonicalPath, listOf("$foldPath/.*"), true, 120000
            )
        }
    }
}
